﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Input = System.Windows.Input;
using System.IO;
using System.Xml.Linq;
using RemoteDesktops.Classes;
using RemoteDesktops.Dialogs;

namespace RemoteDesktops
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// the list of desktops
        /// </summary>
        private Desktops _desktops;
        private bool _canClose;

        /// <summary>
        /// 
        /// </summary>
        public MainWindow()
        {
            this.InitializeComponent();
            this._desktops = new Desktops();
            this._canClose = false;
            this.LoadDesktops();

            this.ContextMenu = (ContextMenu)Window.Resources["MWCM"];
        }

        #region Private Methods
        /// <summary>
        /// Loads the Desktops from Config
        /// </summary>
        private void LoadDesktops()
        {
            try
            {
                foreach (Desktop desktop in this._desktops)
                {
                    AddDesktop(desktop);
                }
            }
            catch
            {
                MessageBox.Show("Error loading desktop data", "Initialize", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// Adds a Desktop to the display and to the right menu's
        /// </summary>
        /// <param name="desktop">The Desktop to Add</param>
        private void AddDesktop(Desktop desktop)
        {
            UpdateDisplay(desktop.Alias, desktop.Id);
        }

        /// <summary>
        /// Creates a menu item
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        private MenuItem CreateMenuItem(String text, int id)
        {
            MenuItem item = new MenuItem()
            {
                Header = text,
                Icon = CreateImage("computer2"),
                Name = String.Format("MenuItem_{0}", id)
            };
            item.Click += new RoutedEventHandler(OnComputerClick);
            return item;
        }

        /// <summary>
        /// Creates an Icon Image
        /// </summary>
        /// <returns>returns and Image</returns>
        private Image CreateImage(string icon)
        {
            Image i = new Image();
            BitmapImage bi = new BitmapImage();
            bi.BeginInit();
            bi.UriSource = new Uri(String.Format("pack://application:,,,/RemoteDesktops;component/Icons/{0}.ico", icon));
            bi.EndInit();
            i.Height = 16;
            i.Width = 16;
            i.Source = bi;
            return i;
        }

        /// <summary>
        /// Updates the main display with the new desktop
        /// </summary>
        private void UpdateDisplay(string alias, Guid id)
        {
            int count = TokenManager.Count;
            TokenManager.Add(id);

            notifyIcon.ContextMenu.Items.Insert(2, CreateMenuItem(alias, count));
            Image i = CreateImage("computer2");
            i.Width = 32;
            i.Height = 32;

            TextBlock block = new TextBlock();
            block.Text = alias;
            block.TextAlignment = TextAlignment.Center;

            StackPanel panel = new StackPanel();
            panel.Margin = new Thickness(5, 20, 5, 0);
            panel.Width = 80;
            panel.Height = 50;
            panel.Children.Add(i);
            panel.Children.Add(block);
            panel.Name = String.Format("Panel_{0}", count);
            panel.MouseEnter += new MouseEventHandler(StackPanel_MouseEnter);
            panel.MouseDown += new MouseButtonEventHandler(StackPanel_MouseDown);
            panel.ContextMenu = CreateContextMenu(count);
            IconWrapPanel.Children.Add(panel);

            AddDesktopMenuItem(alias, count);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="alias"></param>
        /// <param name="key"></param>
        private void AddDesktopMenuItem(string alias, int key)
        {
            if (((MenuItem)DesktopMenu.Items[0]).Name == "Default")
                DesktopMenu.Items.Remove(DesktopMenu.Items[0]);

            MenuItem item = new MenuItem()
            {
                Header = alias,
                Name = String.Format("DM_{0}", key),
                Background = CreateWhiteBackground()
            };

            MenuItem first = new MenuItem()
            {
                Header = "Start",
                Background = CreateWhiteBackground(),
                Name = String.Format("DM_{0}", key),
                Icon = CreateImage("start")
            };
            first.Click += new RoutedEventHandler(LaunchDesktop_Click);

            MenuItem second = new MenuItem()
            {
                Header = "Delete",
                Background = CreateWhiteBackground(),
                Name = String.Format("DM_{0}", key),
                Icon = CreateImage("delete")
            };
            second.Click += new RoutedEventHandler(DeleteDesktop_Click);
            item.Items.Add(first);            
            item.Items.Add(second);
            DesktopMenu.Items.Add(item);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private SolidColorBrush CreateWhiteBackground()
        {
            return new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFE7E7E7"));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private ContextMenu CreateContextMenu(int id)
        {
            ContextMenu menu = new System.Windows.Controls.ContextMenu();
            MenuItem start = new MenuItem();
            MenuItem delete = new MenuItem();
            start.Click += new RoutedEventHandler(LaunchDesktop_Click);
            delete.Click += new RoutedEventHandler(DeleteDesktop_Click);
            start.Header = "Start";
            delete.Header = "Delete";
            start.Name = String.Format("CM_{0}", id);
            delete.Name = String.Format("CM_{0}", id);

            start.Icon = CreateImage("start");
            delete.Icon = CreateImage("delete");

            menu.Items.Add(start);
            //menu.Items.Add(new Separator());
            menu.Items.Add(delete);
            return menu;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        private void RemoveDesktop(Guid id)
        {
            //Remove
            this._desktops.RemoveDesktop(this._desktops.Find(id));
            int key = TokenManager.KeyValue(id);
            for (int i = 0; i < IconWrapPanel.Children.Count; i++)
            {
                if (((StackPanel)IconWrapPanel.Children[i]).Name.Equals(String.Format("Panel_{0}", key), StringComparison.CurrentCultureIgnoreCase))
                {
                    IconWrapPanel.Children.Remove(IconWrapPanel.Children[i]);
                    RemoveNotifyIconMenu(key);
                    RemoveDesktopItem(key);
                    TokenManager.Remove(key);
                    break;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        private void RemoveDesktopItem(int key)
        {
            for (int ix = 0; ix < DesktopMenu.Items.Count; ix++)
            {
                MenuItem item = DesktopMenu.Items[ix] as MenuItem;
                if (item != null)
                {
                    if (item.Name == String.Format("DM_{0}", key))
                    {
                        DesktopMenu.Items.Remove(item);
                        break;
                    }
                }
            }

            //If the last one was removed
            if (DesktopMenu.Items.Count == 0)
            {
                DesktopMenu.Items.Add(
                  new MenuItem()
                  {
                      Header = "No Desktops",
                      Name = "Default",
                      Background = CreateWhiteBackground()
                  }
                );
            }
        }

        /// <summary>
        /// Removes a menu item from the Notify Icon Menu
        /// </summary>
        /// <param name="key"></param>
        private void RemoveNotifyIconMenu(int key)
        {
            for (int ix = 2; ix < notifyIcon.ContextMenu.Items.Count - 2; ix++)
            {
                MenuItem item = notifyIcon.ContextMenu.Items[ix] as MenuItem;
                if (item != null)
                {
                    if (item.Name == String.Format("MenuItem_{0}", key))
                    {
                        notifyIcon.ContextMenu.Items.Remove(item);
                        break;
                    }
                }
            }
        }
        #endregion

        #region Event Handlers

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                int index = Convert.ToInt32(((StackPanel)sender).Name.Split('_')[1]);
                DesktopLauncher.LaunchDesktop(this._desktops.Find(TokenManager.Value(index)).ServerName);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            if (this._canClose)
                base.OnClosing(e);
            else
            {
                this.Hide();
                e.Cancel = true;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnOpenClick(object sender, RoutedEventArgs e)
        {
            this.Show();
            this.WindowState = WindowState.Normal;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnComputerClick(object sender, RoutedEventArgs e)
        {
            LaunchFromMenuItem(sender as MenuItem);
        }

        private void LaunchFromMenuItem(MenuItem item)
        {
            int index = Convert.ToInt32(item.Name.Split('_')[1]);
            DesktopLauncher.LaunchDesktop(this._desktops.Find(TokenManager.Value(index)).ServerName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnExitClick(object sender, RoutedEventArgs e)
        {
            this._canClose = true;
            this.Close();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void notifyIcon_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            this.Show();
            this.BringIntoView();
            this.WindowState = WindowState.Normal;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void NewDesktop_Click(object sender, RoutedEventArgs e)
        {
            CreateDesktop();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StackPanel_MouseEnter(object sender, MouseEventArgs e)
        {
            try
            {
                string alias = ((TextBlock)((StackPanel)sender).Children[1]).Text;
                //Look up the desktop     
                Desktop desktop = this._desktops.Find(alias);
                ToolTip t = new ToolTip();
                //Create the tooltip      
                t.Content = String.Format("Server Name: {0}\r\nDescripton: {1}", desktop.ServerName, desktop.Description);
                ((StackPanel)sender).ToolTip = t;
            }
            catch
            { }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LaunchDesktop_Click(object sender, RoutedEventArgs e)
        {
            LaunchFromMenuItem(sender as MenuItem);
        }

        private void CreateDesktop()
        {
            AddDesktop desktop = new AddDesktop();
            desktop.DesktopList = this._desktops;
            desktop.Owner = this;
            desktop.ShowDialog();
            if (desktop.Add)
            {
                Guid id = Guid.NewGuid();
                this._desktops.AddDesktop(new Desktop(desktop.Alias, desktop.ServerName, desktop.Description, id));
                UpdateDisplay(desktop.Alias, id);
            }
        }

        private void CreateDesktop_Click(object sender, RoutedEventArgs e)
        {
            CreateDesktop();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DeleteDesktop_Click(object sender, RoutedEventArgs e)
        {
            int index = Convert.ToInt32((sender as MenuItem).Name.Split('_')[1]);
            RemoveDesktop(TokenManager.Value(index));
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AboutMenuItem_Click(object sender, RoutedEventArgs e)
        {
            RemoteDesktops.Dialogs.About about = new About();
            about.Owner = this;
            about.ShowDialog();
        }
    }
}